<?php
/**
 * 京东客户端
 *
 * User: Ken.Zhang <kenphp@yeah.net>
 * Date: 2019-05-12
 */
class JdClient {

    /**
     * 分配给应用的AppKey
     */
    public $appKey;

    /**
     * 密钥
     */
    public $secretkey;

    /**
     * 网关
     */
    public $gateWay = JD_API_GW_URI;

    /**
     * Oauth2颁发的动态令牌,暂不支持使用
     */
    public $accessToken = '';

    /**
     * 响应格式。暂时只支持json
     */
    public $format = 'json';

    /**
     * API协议版本，可选值：2.0
     */
    public $v = '1.0';

    /**
     * 签名的摘要算法， md5
     */
    public $signMethod = 'md5';

    /**
     * 请求结果
     */
    private $result;


    /**
     * 执行一个请求
     *
     * @param object $req
     * @param mixed $session
     * @return mixed
     */
    public function execute($req, $session=null)
    {
        try {
            $this->accessToken = $session;

            // 系统参数
            $params = [
                'method' => $req->getApiMethodName(),
                'app_key' => $this->appKey,
                'timestamp' => date('Y-m-d H:i:s', time()),
                'format' => $this->format,
                'v' => $this->v,
                'sign_method' => $this->signMethod,
                'param_json' => json_encode($req->apiParams),
            ];
            if ($this->accessToken)
                $params['access_token'] = $this->accessToken;

            $params['sign'] = $this->makeRequestSign($params);

            $this->httpRequestPost($this->gateWay, $params);

            return $req->getResult($this->result);
        } catch (\Exception $e) {
            $this->writeLogs('File: ' . $e->getFile() .  ' Line: ' . $e->getLine() . ' Error: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * POST 请求方法
     *
     * @param   $uri    string
     * @param   $params array
     * @throws Exception
     */
    private function httpRequestPost($uri, $params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $uri);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_POST, true);
        //https 请求
        if (strlen($uri) > 5 && strtolower(substr($uri,0,5)) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }

        // 数据格式
        if (is_array($params) && 0 < count($params)) {
            $postBodyString = '';
            foreach ($params as $k => $v)
            {
                $postBodyString .= $k.'=' . urlencode($v) . '&';
            }
            unset($k, $v);
            curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString,0,-1));
        }

        $resp = curl_exec($ch);

        if (curl_errno($ch))
            throw new Exception(curl_error($ch),0);

        $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if (200 !== $httpStatusCode)
            throw new Exception($resp, $httpStatusCode);

        curl_close($ch);

        $this->result = $resp;
    }

    /**
     * 生成请求签名
     *
     * @param   $params     array
     * @return  string
     */
    private function makeRequestSign($params)
    {
        ksort($params);

        $stringToBeSigned = $this->secretkey;
        foreach ($params as $k => $v)
        {
            $stringToBeSigned .= "$k$v";
        }
        unset($k, $v);
        $stringToBeSigned .= $this->secretkey;

        return strtoupper(md5($stringToBeSigned));
    }
    
    /**
     * 写日志
     *
     * @param   $msg    string
     */
    private function writeLogs($msg)
    {
        if (!JD_SDK_MODEL)
            return ;

        try {
            $logDir = JD_SDK_LOG_DIR.date('Ym', time());
            $logFileName = $logDir.'/'.date('Y-m-d', time()).'.log';
            if (!is_dir($logDir)) mkdir($logDir, 0755, true);

            $text = date('Y-m-d H:i:s', time()).PHP_EOL;
            $text .= $msg.PHP_EOL.PHP_EOL;
            file_put_contents($logFileName, $text, FILE_APPEND);

        } catch (\Exception $e) {

        }
    }

}